﻿//
//  HFHttpFactory.m
//  HFBaseLibModule
//
//  Created by Points on 2020/4/3.
//  Copyright © 2020 hfqf123@126.com. All rights reserved.
//

#import "HFHttpFactory.h"
#import "HFBaseHTTPRequestManager.h"
#import "HFLogger.h"
#import "HFParamsRSAEncryptUtil.h"
#import "HFSecurity.h"
#import <HFAppGroupIdModule/HFAppGroupUtil.h>

@interface HFHttpFactory()

@end

@implementation HFHttpFactory

+ (instancetype)factory {
    HFHttpFactory *factory = [[self alloc] init];
    factory.needToast = YES;
    // rsa加解密结果 默认成功
    factory.rsaEncryptResult = YES;
    // rsa加解密开关 默认关闭 兼容老版本
    factory.rsaSwitch = NO;
    return factory;
}

- (void)dealloc {
    HFLogger(@"%s", __func__);
}

- (id<HFHttpAbstractFactory> (^)(NSString *))setDomain{
    __weak typeof(self) weakSelf = self;
    return ^(NSString *domain){
        weakSelf.mDomain = domain;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(BOOL))setRsaSwitch{
    __weak typeof(self) weakSelf = self;
       return ^(BOOL rsaSwitch){
          weakSelf.rsaSwitch = rsaSwitch;
          return weakSelf;
      };
}

- (id<HFHttpAbstractFactory> (^)(NSString *))setPath{
    __weak typeof(self) weakSelf = self;
    return ^(NSString *path){
        NSDictionary *dictionary = HFBaseHTTPRequestManager.manager.baseURLDictionary[weakSelf.mDomain];
        weakSelf.mPath = [NSString stringWithFormat:@"%@/%@/%@", dictionary[@"domain"], dictionary[@"path"], path];
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(NSDictionary *))setRequest{
    __weak typeof(self) weakSelf = self;
    return ^(NSDictionary *para){
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateFormat = @"yyyyMMddHHmmss";

        //添加基础参数
        NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:HFBaseHTTPRequestManager.manager.baseParameters];
        [dict setValue:[dateFormatter stringFromDate:NSDate.date] forKey:@"base_qqsj"];
        [dict addEntriesFromDictionary:para];
        
        // 请求参数rsa加密
        if (weakSelf.rsaSwitch) {
            NSDictionary *resultDic = [[HFParamsRSAEncryptUtil paramsRSAEncryptUtil] encryptParams:dict];
            weakSelf.mPara = resultDic;
        }else{
            weakSelf.mPara = dict;
        }
        return weakSelf;

    };
}

- (id<HFHttpAbstractFactory> (^)(NSString *))setImageName {
    __weak typeof(self) weakSelf = self;
    return ^(NSString *imageName) {
        weakSelf.mImageName = imageName;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(NSString *))setFileName{
    __weak typeof(self) weakSelf = self;
    return ^(NSString *fileName) {
        weakSelf.mFileName = fileName;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(NSData *))setImage {
    __weak typeof(self) weakSelf = self;
    return ^(NSData *image){
        weakSelf.mImage = image;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(NSArray *))setImageArray {
    __weak typeof(self) weakSelf = self;
    return ^(NSArray *imageArray){
        weakSelf.mImageArray = imageArray;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(NSString *))setMimeType {
    __weak typeof(self) weakSelf = self;
    return ^(NSString *mimeType){
        weakSelf.mMimeType = mimeType;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(HFHttpSucceedBlock))setResponseBlock{
    __weak typeof(self) weakSelf = self;
    return ^(HFHttpSucceedBlock block){
        weakSelf.mSucceedBlock = block;
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(HFHttpFailedBlock))setErrorBock{
    __weak typeof(self) weakSelf = self;
    return ^(HFHttpFailedBlock block){
        weakSelf.mFailedBlock = block;
        return weakSelf;
    };
}

/// 子工厂中实现各自的post请求方法
- (id<HFHttpAbstractFactory> (^)(void))post {
    __weak typeof(self) weakSelf = self;
    return ^(void) {
        return weakSelf;
    };
}

/// 子工厂中实现各自的get请求方法
- (id<HFHttpAbstractFactory> (^)(void))get{
    __weak typeof(self) weakSelf = self;
    return ^(void){
        return weakSelf;
    };
}

/// 子工厂中实现各自的单图上传请求方法
- (id<HFHttpAbstractFactory> (^)(void))singleUpload {
    __weak typeof(self) weakSelf = self;
    return ^(void) {
        return weakSelf;
    };
}

/// 子工厂中实现各自的多图上传请求方法
- (id<HFHttpAbstractFactory> (^)(void))multiUpload {
    __weak typeof(self) weakSelf = self;
    return ^(void) {
        return weakSelf;
    };
}

- (id<HFHttpAbstractFactory> (^)(BOOL))setNeedToast{
    __weak typeof(self) weakSelf = self;
       return ^(BOOL needToast){
          weakSelf.needToast = needToast;
          return weakSelf;
      };
}

- (COPromise<COTuple *> *(^)(void))coPost{
    __weak typeof(self) weakSelf = self;
    COPromise<COTuple *>* promise = [COPromise promise];
       return ^(void){
           weakSelf.promise = promise;
          return promise;
      };
}

- (id<HFHttpAbstractFactory> (^)(HFHttpDelayBlock))setDelayOperationBlock{
    __weak typeof(self) weakSelf = self;
    return ^(HFHttpDelayBlock block){
        weakSelf.delayOperationBlock = block;
        return weakSelf;
    };
}
#pragma mark - getter
- (COPromise<COTuple *> *)promise{
    if(!_promise){
        _promise = [COPromise promise];
    }
    return _promise;
}

+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString{
    if (jsonString == nil) {
        return nil;
    }

    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    if(err)
    {
        NSLog(@"json解析失败：%@",err);
        return nil;
    }
    return dic;
}

- (void)startDelayTimer:(NSURLSessionTask *)task{
    if (self.delayOperationBlock) {
        HFHttpDelayBlock delay = self.delayOperationBlock;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (task.state == NSURLSessionTaskStateRunning) {
                if (delay) {
                    delay();
                }
            }
        });
    }
   
}

#pragma mark - utils
+ (void)requestSuccessWithTask:(NSURLSessionDataTask *)task
                          body:(NSDictionary *)body
                responseObject:(id)responseObject
                successHandler:(HFHttpSucceedBlock)successHandler
                     needToast:(BOOL)needToast
                     rsaSwitch:(BOOL)rsaSwitch{
    HFHttpResonseModule *module = [HFHttpResonseModule yy_modelWithJSON:responseObject];
    module.responseObject = responseObject;
    module.task = task;

    if (rsaSwitch) {
        // 需要rsa解密 module.result是加密过的字符串
        if (module.state.intValue==0 || module.state.intValue == 1) {
            NSString *resultString = (NSString *)module.result;
            NSString *key = [HFSecurity randomAESKey];
            if (resultString && resultString.length>0 && [resultString isKindOfClass:NSString.class]){
                // 符合条件才进行解密
                resultString = [resultString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                NSString *rsaResultString = [HFSecurity aes256DecryptStringWithString:resultString key:key];
                if (rsaResultString&&rsaResultString.length>0) {
                    // 解密成功
                    id result = [HFHttpFactory dictionaryWithJsonString:rsaResultString];
                    module.result = result;
                    NSMutableDictionary *_responseObject = [NSMutableDictionary dictionaryWithDictionary:responseObject];
                    if (result) {
                        [_responseObject setValue:result forKey:@"result"];
                    }
                    module.result = result;
                    module.responseObject = _responseObject;
                }else{
                    // 解密失败
                    module.state = @"1";
                    module.result = nil;
                    module.message = kRSAEncryptFailTip;
                }
            }else{
                module.result = nil;
            }
            
            NSString *v2 = body[@"v2"];
            if (v2 && [v2 isKindOfClass:NSString.class] && v2.length>0) {
                v2 = [v2 stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                NSString *v2DesString = [HFSecurity aes256DecryptStringWithString:v2 key:key];
                body = [HFHttpFactory dictionaryWithJsonString:v2DesString];
            }
            HFLogger(@"\n%@\n%@\n%@",task.originalRequest.URL, body, module.responseObject);
        }
    }

    if (successHandler) successHandler(module);
    switch ([module.state intValue]) {
        case 0:
            break;
        case 1:
            if(needToast){
                [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:module.message];
            }
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
        case 2:
            [[NSNotificationCenter defaultCenter]postNotificationName:HFForceUpgrade object:module.message];
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
        case 200:
            if (![task.currentRequest.URL.absoluteString containsString:@"collect/collectMessage"]) {
                [self logoutUser];
            }
            if(needToast){
                [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:module.message];
            }
            
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
        default:
            if(needToast){
                [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:kInterfaceException];
            }
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
    }
}

+ (void)requestFailureWithTask:(NSURLSessionDataTask *)task
                         param:(NSDictionary *)param
                         error:(NSError *)error
                failureHandler:(HFHttpFailedBlock)failureHandler
                     needToast:(BOOL)needToast {
    HFHttpError *httpError = [HFHttpError errorWithDomain:error.domain code:error.code userInfo:error.userInfo];
    if(needToast){
        [self showNetworkError:httpError.code task:task];
    }
    [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryError object:@{
        @"url":task.originalRequest.URL.absoluteString,
        @"error":error,
        @"paras":param//章鱼贝贝
    }];
    if (failureHandler) failureHandler(httpError);
}

+ (void)logoutUser {
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"HF_base_uid"];
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"HF_base_TokenID"];
    [[[NSUserDefaults alloc]initWithSuiteName:[HFAppGroupUtil appGroupID]]removeObjectForKey:@"HF_base_uid"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"KEY_HTTP_TOKEN_EXPIRED" object:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"KEY_NOTI_CLEAR_JGTAGS" object:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"logOut" object:nil];
}

+ (void)showNetworkError:(NSInteger)code task:(NSURLSessionDataTask *)task{
    switch (code) {
        case NSURLErrorTimedOut:
        case NSURLErrorServerCertificateUntrusted:
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:kNetWorkException];
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryNetWorkException object:task.originalRequest.URL.absoluteString];
            break;
        case NSURLErrorNotConnectedToInternet:
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:kNetWorkException];
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryNetWorkException object:task.originalRequest.URL.absoluteString];
            break;
        default:
            break;
    }
}

#pragma mark - coobjc
+ (void)requestSuccessWithTask4Cobjc:(NSURLSessionDataTask *)task
                          body:(NSDictionary *)body
                responseObject:(id)responseObject
                successHandler:(HFHttpSucceedBlock)successHandler
                     needToast:(BOOL)needToast
                     rsaSwitch:(BOOL)rsaSwitch
                       promise:(COPromise<COTuple *>*)promise
{
    HFHttpResonseModule *module = [HFHttpResonseModule yy_modelWithJSON:responseObject];
    module.responseObject = responseObject;
    module.task = task;

    if (rsaSwitch) {
        if (module.state.intValue == 0 || module.state.intValue == 1) {
            // 需要rsa解密 module.result是加密过的字符串
            NSString *resultString = (NSString *)module.result;
            NSString *key = [HFSecurity randomAESKey];
            if (resultString && resultString.length>0 && [resultString isKindOfClass:NSString.class]){
                // 符合条件才进行解密
                resultString = [resultString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                NSString *rsaResultString = [HFSecurity aes256DecryptStringWithString:resultString key:key];
                if (rsaResultString&&rsaResultString.length>0) {
                    // 解密成功
                    id result = [HFHttpFactory dictionaryWithJsonString:rsaResultString];
                    module.result = result;
                    NSMutableDictionary *_responseObject = [NSMutableDictionary dictionaryWithDictionary:responseObject];
                    if (result) {
                        [_responseObject setValue:result forKey:@"result"];
                    }
                    module.result = result;
                    module.responseObject = _responseObject;
                }else{
                    // 解密失败
                    module.state = @"1";
                    module.result = nil;
                    module.message = kRSAEncryptFailTip;
                }
            }else{
                module.result = nil;
            }
            
            NSString *v2 = body[@"v2"];
            if (v2 && [v2 isKindOfClass:NSString.class] && v2.length>0) {
                v2 = [v2 stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                NSString *v2DesString = [HFSecurity aes256DecryptStringWithString:v2 key:key];
                body = [HFHttpFactory dictionaryWithJsonString:v2DesString];
                
            }
            HFLogger(@"\n%@\n%@\n%@",task.originalRequest.URL, body, module.responseObject);
        }
    }

    [promise fulfill:co_tuple(@(YES), module.responseObject)];
    switch ([module.state intValue]) {
        case 0:
            break;
        case 2:
            [[NSNotificationCenter defaultCenter]postNotificationName:HFForceUpgrade object:module.message];
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
        case 200:
            if (![task.currentRequest.URL.absoluteString containsString:@"collect/collectMessage"]) {
                [self logoutUser];
            }
            if(needToast){
                [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:module.message];
            }
            
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
        default:
            if(needToast){
                [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryShowToast object:module.message];
            }
            [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryRespFail object:@{
                @"url":task.originalRequest.URL.absoluteString,
                @"body":body,
                @"resp":module.responseObject,
                @"paras":body,//章鱼贝贝新增
            }];
            break;
    }
}

+ (void)requestFailureWithTask4Cobjc:(NSURLSessionDataTask *)task
                               param:(NSDictionary *)param
                               error:(NSError *)error
                      failureHandler:(HFHttpFailedBlock)failureHandler
                           needToast:(BOOL)needToast
                             promise:(COPromise<COTuple *>*)promise{
    HFHttpError *httpError = [HFHttpError errorWithDomain:error.domain code:error.code userInfo:error.userInfo];
    if(needToast){
        [self showNetworkError:httpError.code task:task];
    }
    [[NSNotificationCenter defaultCenter]postNotificationName:HFHttpFactoryError object:@{
        @"url":task.originalRequest.URL.absoluteString,
        @"error":error,
        @"paras":param//章鱼贝贝
    }];
    [promise fulfill:co_tuple(@(NO), httpError)];
}

@end

